package yb.ecp.fast.user.manager;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import yb.ecp.fast.infra.infra.log.LogHelper;
import yb.ecp.fast.infra.util.ObjectUtil;
import yb.ecp.fast.infra.util.StringUtil;
import yb.ecp.fast.user.infra.ErrorCode;

import java.util.Set;

/**
 * Created by john on 2017/4/27.
 */
@Component
public class UserContextManager {
    @Autowired
    private JedisPool jedisPool;

    @Value("${fast.user.session.ttl:2000}")
    int sessionTtl;//秒数

    public static final String REDIS_EXCEPTION = "redis exception";
    public static final String SPACE_ID = "spaceId:";
    public static final String AUTH = "auth:";
    public static final String DATA = "data:";

    public ErrorCode cacheUser(String userId, Object data, Integer[] codes, String workspaceId) {
        ErrorCode cacheUserData = cacheUserData(userId, data);

        if (0 != cacheUserData.getCode()) {
            return ErrorCode.FailedToCacheUserDate;
        }
        if (null != codes) {
            ErrorCode cacheAuthCode = cacheAuthCode(userId, codes);

            if (0 != cacheAuthCode.getCode()) {
                return ErrorCode.FailedToCacheAuthCode;
            }
        }

        if (!StringUtil.isNullOrEmpty(workspaceId)) {
            ErrorCode cacheWSCode = cacheWorkspase(userId, workspaceId);
            if (0 != cacheWSCode.getCode()) {
                return ErrorCode.FailedToCacheUserDate;
            }
        }

        ErrorCode renewLeaseSession = renewLeaseSession(userId);
        if (0 != renewLeaseSession.getCode()) {
            return ErrorCode.FailedToRenewLeaseSession;
        }

        return ErrorCode.Success;
    }

    public ErrorCode cacheWorkspase(String userId, String workspaseId) {
        Jedis jedis = new Jedis();
        try {

            jedis = jedisPool.getResource();
            String dataKey = SPACE_ID + userId;
            boolean cached = jedis.exists(dataKey);
            if (cached) {
                jedis.del(dataKey);
            }
            jedis.set(dataKey, workspaseId);


        } catch (Exception e) {
            LogHelper.fatal(REDIS_EXCEPTION, e);
        } finally {
            jedis.close();
        }
        return ErrorCode.Success;
    }


    public ErrorCode renewLeaseSession(String userId) {
        Integer ttl = sessionTtl;
        Jedis jedis = new Jedis();
        try {
            jedis = jedisPool.getResource();
            String authKey = AUTH + userId;
            boolean cached = jedis.exists(authKey);
            if (!cached) {
                jedis.expire(authKey, ttl);
            }

            String dataKey = DATA + userId;
            cached = jedis.exists(dataKey);
            if (cached) {
                jedis.expire(dataKey, ttl);
            }

            String spaceKey = SPACE_ID + userId;
            cached = jedis.exists(spaceKey);
            if (cached) {
                jedis.expire(spaceKey, ttl);
            }

        } catch (Exception e) {
            LogHelper.fatal(REDIS_EXCEPTION, e);
        } finally {
            jedis.close();
        }
        return ErrorCode.Success;
    }

    public ErrorCode checkAuthCode(String userId, Integer code) {
        Jedis jedis = new Jedis();
        try {
            jedis = jedisPool.getResource();
            String authKey = AUTH + userId;

            boolean cached = jedis.exists(authKey);
            if (!cached) {
                return ErrorCode.NeedLogin;
            }

            boolean hasCode = jedis.sismember(authKey, Integer.toString(code));
            if (hasCode) {
                return ErrorCode.Success;
            }
        } catch (Exception e) {
            LogHelper.fatal(REDIS_EXCEPTION, e);
        } finally {
            jedis.close();
        }
        return ErrorCode.NoAuthorization;
    }

    public Object getUserData(String userId) {
        Jedis jedis = new Jedis();
        try {
            jedis = jedisPool.getResource();
            String dataKey = DATA + userId;
            boolean cached = jedis.exists(dataKey);
            if (!cached) {
                return null;
            }
            return ObjectUtil.deserialize(jedis.get(dataKey.getBytes()));
        } catch (Exception e) {
            LogHelper.fatal(REDIS_EXCEPTION, e);
        } finally {
            jedis.close();
        }
        return null;
    }

    public String getWorkspaceId(String userId) {
        Jedis jedis = new Jedis();
        try {
            jedis = jedisPool.getResource();
            String dataKey = SPACE_ID + userId;
            boolean cached = jedis.exists(dataKey);
            if (!cached) {
                return null;
            }
            return String.valueOf(jedis.get(dataKey));
        } catch (Exception e) {
            LogHelper.fatal(REDIS_EXCEPTION, e);
        } finally {
            jedis.close();
        }
        return null;

    }

    public ErrorCode cacheUserData(String userId, Object data) {
        Jedis jedis = new Jedis();
        try {
            jedis = jedisPool.getResource();
            String dataKey = DATA + userId;
            boolean cached = jedis.exists(dataKey);
            if (cached) {
                jedis.del(dataKey);
            }
            jedis.set(dataKey.getBytes(), ObjectUtil.serialize(data));
        } catch (Exception e) {
            LogHelper.fatal(REDIS_EXCEPTION, e);
        } finally {
            jedis.close();
        }
        return ErrorCode.Success;

    }

    public Integer[] getAuthCode(String userId) {
        Jedis jedis = new Jedis();

        try {

            jedis = jedisPool.getResource();
            String authKey = AUTH + userId;
            boolean cached = jedis.exists(authKey);
            if (!cached) {
                return null;
            }
            Set<String> codesSet = jedis.smembers(authKey);
            Integer[] codes = new Integer[codesSet.size()];
            int i = 0;
            for (String code : codesSet) {
                codes[i] = Integer.parseInt(code);
                ++i;
            }
            return codes;

        } catch (Exception e) {
            LogHelper.fatal(REDIS_EXCEPTION, e);
        } finally {
            jedis.close();
        }
        return null;
    }

    public ErrorCode cacheAuthCode(String userId, Integer[] codes) {
        Jedis jedis = new Jedis();
        try {
            jedis = jedisPool.getResource();
            String authKey = AUTH + userId;
            boolean cached = jedis.exists(authKey);
            if (cached) {
                jedis.del(authKey);
            }
            for (int code : codes) {
                jedis.sadd(authKey, Integer.toString(code));
            }

        } catch (Exception e) {
            LogHelper.fatal(REDIS_EXCEPTION, e);
        } finally {
            jedis.close();
        }
        return ErrorCode.Success;
    }

    public ErrorCode clearSession(String userId) {
        if (userId == null) {
            return ErrorCode.Success;
        }
        Jedis jedis = new Jedis();
        try {
            jedis = jedisPool.getResource();
            String authKey = AUTH + userId;
            boolean cached = jedis.exists(authKey);
            if (cached) {
                jedis.del(authKey);
            }

            String dataKey = DATA + userId;
            cached = jedis.exists(dataKey);
            if (cached) {
                jedis.del(dataKey);
            }

            String spaceKey = SPACE_ID + userId;
            cached = jedis.exists(spaceKey);
            if (cached) {
                jedis.del(spaceKey);
            }

        } catch (Exception e) {
            LogHelper.fatal(REDIS_EXCEPTION, e);

        } finally {
            jedis.close();
        }
        return ErrorCode.Success;
    }
}
